﻿#include "GUIGeometryStretchDialog.h"
#include "ui_GUIGeometryStretchDialog.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITK_Kernel/FITKCore/FITKOperatorRepo.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsGeometryData.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKGeoInterfaceFactory.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoModelOperLine.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeomTools.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoModelPoint.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoModelSurface.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoModelSolid.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoModelSurface.h"


#include "PickDataProvider/GUIPickInfo.h"
#include "FITK_Kernel/FITKCore/FITKActionOperator.h"
#include "OperatorsInterface/GraphEventOperator.h"

#include "PickDataProvider/PickedData.h"
#include "PickDataProvider/PickedDataProvider.h"
#include "GraphDataProvider/GraphDataCalculate.h"
#include <QMessageBox>

namespace GUI {

    GUIGeometryStretchDialog::GUIGeometryStretchDialog(Core::FITKActionOperator* oper, QWidget* parent)
        : GUIGeometryBaseDialog(nullptr, oper, parent), _ui(new Ui::GUIGeometryStretchDialog)
    {
        _ui->setupUi(this);
        //告知基类，默认创建有限线段对象
        this->createGeometryObj(Interface::FITKGeoEnum::FITKGeometryComType::FGTSegment);
        this->init();
    }

    GUIGeometryStretchDialog::GUIGeometryStretchDialog(Interface::FITKAbsGeoModelSegment* obj, Core::FITKActionOperator* oper, QWidget* parent)
        : GUIGeometryBaseDialog(obj, oper, parent), _ui(new Ui::GUIGeometryStretchDialog)
    {
        _ui->setupUi(this);
        this->init();
    }

    GUIGeometryStretchDialog::~GUIGeometryStretchDialog()
    {
        if (_ui) {
            delete _ui;
            _ui = nullptr;
        }
    }

    void GUIGeometryStretchDialog::init()
    {
        setWindowTitle(tr("Stretch"));//拉伸
        Interface::FITKAbsGeoModelSegment* geoData = dynamic_cast<Interface::FITKAbsGeoModelSegment*>(_obj);
        Acoustics::FITKAcousticsGeometryData* geometryData = FITKAPP->getGlobalData()->getGeometryData<Acoustics::FITKAcousticsGeometryData>();

        if (!geometryData || !geoData) return;
        //获取数据
        QString name = geometryData->checkName(tr("Curve-1"));
        if (!_isCreate) name = _obj->getDataObjectName();

        //设置默认被拉伸类型
        QVariant selectType(GUI::GUIPickInfo::POBJGeometryVert);
        _ui->stretch_type->setProperty("selectType", selectType);


        //设置界面
        _ui->lineEdit_Name->setText(name);
        //设置拉伸方向初始化为0
        _ui->lineEdit_X->setText(QString::number(0));
        _ui->lineEdit_Y->setText(QString::number(0));
        _ui->lineEdit_Z->setText(QString::number(0));
        //设置拉伸长度初始化为0
        _ui->lineEdit_Value->setText(QString::number(0));


        _ui->stretch_type->addItem("Point");//拉伸目标：点
        _ui->stretch_type->addItem("Curve");//拉伸目标：线
        _ui->stretch_type->addItem("Surface");//拉伸目标：面
    }

    QString GUIGeometryStretchDialog::getNameText()
    {
        return _ui->lineEdit_Name->text();
    }

    void GUIGeometryStretchDialog::pickFinishedOper()
    {
        //获取拾取数据
        GraphData::PickedDataProvider* provider = GraphData::PickedDataProvider::getInstance();
        if (provider == nullptr)return;
        disconnect(provider, SIGNAL(sig_pickedOver()), this, SLOT(slotPickOverEvent()));
        QList<GraphData::PickedData*> pickList = provider->getPickedList();

        QVariant var = _ui->stretch_type->property("selectType");
        if (var.canConvert<GUI::GUIPickInfo::PickObjType>())
        {
            GUI::GUIPickInfo::PickObjType typeData = var.value<GUI::GUIPickInfo::PickObjType>();
            switch (typeData)
            {
            case GUI::GUIPickInfo::POBJGeometryVert:
            {
                //由点创建线的逻辑
                QList<int> idList = {};
                QList<int> PickedIds;
                for (GraphData::PickedData* pickData : pickList) {
                    if (pickData == nullptr)continue;
                    idList.append(pickData->getPickedDataObjId());
                    PickedIds = pickData->getPickedIds();
                }
                //获取拾取的数据
                if (idList.isEmpty()) return;
                Interface::FITKAbsGeoModelSegment*lineP = dynamic_cast<Interface::FITKAbsGeoModelSegment*>(_obj);
                //根据id获取起始点的xyz
                std::array<double, 3> origin = this->getPointXYZ(PickedIds.at(0));
                lineP->setStartPoint(origin.at(0), origin.at(1), origin.at(2));

            }
            break;
            case GUI::GUIPickInfo::POBJGeometryEdge:
            {
                //由线创面
                Interface::FITKAbsGeoModelExtrudeSurface*faceP = dynamic_cast<Interface::FITKAbsGeoModelExtrudeSurface*>(_obj);
                QList<Interface::VirtualShape> edges;
                for (GraphData::PickedData* pickData : pickList) {
                    if (pickData == nullptr)continue;
                    int cmdID = pickData->getPickedDataObjId();
                    QHash<int, int>OtherIDs = pickData->getPickedOtherIDs();
                    for (int i : pickData->getPickedIds())
                    {
                        if (OtherIDs.contains(i) == true)
                        {
                            Interface::VirtualShape temp(cmdID, i, OtherIDs.value(i));
                            edges.push_back(temp);
                        }
                    }
                }
                faceP->setSourceCurve(edges.at(0));
            }
            break;
            case GUI::GUIPickInfo::POBJGeometryFace:
            {
                //由面创建体的逻辑
                QList<Interface::VirtualShape> edges;
                for (GraphData::PickedData* pickData : pickList) {
                    if (pickData == nullptr)continue;
                    int cmdID = pickData->getPickedDataObjId();
                    QHash<int, int>OtherIDs = pickData->getPickedOtherIDs();//key PickedId  value index
                    for (int i : pickData->getPickedIds())
                    {
                        if (OtherIDs.contains(i) == true)
                        {
                            Interface::VirtualShape temp(cmdID, i, OtherIDs.value(i));
                            edges.push_back(temp);
                        }
                    }
                }

                Interface::FITKAbsGeoModelExtrudeSolid*SolidP = dynamic_cast<Interface::FITKAbsGeoModelExtrudeSolid*>(_obj);
                if (SolidP == nullptr)
                {
                    return;
                }
                //赋值方向
                double x = _ui->lineEdit_X->text().toDouble();
                double y = _ui->lineEdit_Y->text().toDouble();
                double z = _ui->lineEdit_Z->text().toDouble();
                double Value = _ui->lineEdit_Value->text().toDouble();
                SolidP->setDirection(x, y, z);
                //赋值长度
                SolidP->setLength(Value);

                if (edges.size() == 0)
                {
                    return;
                }
                SolidP->setSourceSurface(edges.at(0));
            }
            break;
            default:
                break;
            }

        }
        this->direction_updata();//更新方向
    }

    void GUIGeometryStretchDialog::getDataFormWidget()
    {
        QVariant var = _ui->stretch_type->property("selectType");
        if (var.canConvert<GUI::GUIPickInfo::PickObjType>())
        {
            GUI::GUIPickInfo::PickObjType typeData = var.value<GUI::GUIPickInfo::PickObjType>();
            switch (typeData)
            {
            case GUI::GUIPickInfo::POBJGeometryVert:
            {
                Interface::FITKAbsGeoModelSegment*lineP = dynamic_cast<Interface::FITKAbsGeoModelSegment*>(_obj);

                //起点在pickFinishedOper函数中赋值
                std::array<double, 3> origin = lineP->startPoint();


                //由点拉伸线时候的方向
                double x = _ui->lineEdit_X->text().toDouble();
                double y = _ui->lineEdit_Y->text().toDouble();
                double z = _ui->lineEdit_Z->text().toDouble();
                //拉伸长度
                double length = _ui->lineEdit_Value->text().toDouble();

                //起始点
                double originAry[3] = { origin.at(0),origin.at(1),origin.at(2) };
                //方向
                double xyz[3] = { x,y,z };

                //计算得出的终点
                double endPoint[3] = { 0.0,0.0,0.0 };
                //通过起点和拉伸方向和长度，计算终点坐标
                GraphData::GraphDataCalculate::calculateLineEndPoint(originAry, xyz, length, endPoint);

                lineP->setDataObjectName(_ui->lineEdit_Name->text());//更新线名称

                //起点
                lineP->setStartPoint(
                    originAry[0],
                    originAry[1],
                    originAry[2]
                );

                lineP->setEndPoint(
                    endPoint[0],
                    endPoint[1],
                    endPoint[2]

                );
                lineP->update();
            }
            break;
            case GUI::GUIPickInfo::POBJGeometryEdge:
            {

                Interface::FITKAbsGeoModelExtrudeSurface*FaceP = dynamic_cast<Interface::FITKAbsGeoModelExtrudeSurface*>(_obj);
                if (FaceP == nullptr)
                {
                    return;
                }
                FaceP->setDataObjectName(_ui->lineEdit_Name->text());//更新面名称
                double Value = _ui->lineEdit_Value->text().toDouble();
                //赋值长度
                FaceP->setLength(Value);
                //赋值方向
                double x = _ui->lineEdit_X->text().toDouble();
                double y = _ui->lineEdit_Y->text().toDouble();
                double z = _ui->lineEdit_Z->text().toDouble();
                FaceP->setDirection(x, y, z);
            }
            break;
            case GUI::GUIPickInfo::POBJGeometryFace:
            {
                Interface::FITKAbsGeoModelExtrudeSolid*SolidP = dynamic_cast<Interface::FITKAbsGeoModelExtrudeSolid*>(_obj);
                if (SolidP == nullptr)
                {
                    return;
                }
                SolidP->setDataObjectName(_ui->lineEdit_Name->text());//更新体名称
                double Value = _ui->lineEdit_Value->text().toDouble();
                //赋值长度
                SolidP->setLength(Value);
                //赋值方向
                double x = _ui->lineEdit_X->text().toDouble();
                double y = _ui->lineEdit_Y->text().toDouble();
                double z = _ui->lineEdit_Z->text().toDouble();
                SolidP->setDirection(x, y, z);
            }
            break;
            case GUI::GUIPickInfo::POBJGeometrySolid:
                break;
            default:
                break;
            }
        }
    }

    void GUIGeometryStretchDialog::OnpickInProcess()
    {
        //转换为string，拾取到的点的个数
        QString number = "(" + QString::number(m_pick_num) + ")";
        _ui->Pick_num->setText(number);
    }

    void GUIGeometryStretchDialog::on_stretch_type_activated(int type)
    {
        //在切换拾取模式后，将清空对3维的操作
        GraphData::PickedDataProvider* provider = GraphData::PickedDataProvider::getInstance();
        if (provider == nullptr)return;
        provider->clearPickedData();//清空拾取数据
        //拾取对象 关闭
        //拾取方式 空
        GUI::GUIPickInfoStru pickInfo = GUI::GUIPickInfo::GetPickInfo();
        pickInfo._pickObjType = GUI::GUIPickInfo::PickObjType(GUI::GUIPickInfo::POBJNone);
        pickInfo._pickMethod = GUI::GUIPickInfo::PickMethod(GUI::GUIPickInfo::PickMethod::PMNone);
        //设置拾取方式
        GUI::GUIPickInfo::SetPickInfo(pickInfo);


        //切换时时，清理方向显示
        EventOper::GraphEventOperator*operGraph = FITKOPERREPO->getOperatorT<EventOper::GraphEventOperator>("OperGraphTool");
        if (operGraph != nullptr)
        {
            operGraph->deleteToolObject(m_direction);
        }

        //重新创建一个显示工具
        EventOper::GraphEventOperator*againoperGraph = FITKOPERREPO->getOperatorT<EventOper::GraphEventOperator>("OperGraphTool");
        if (againoperGraph != nullptr)
        {
            m_direction = againoperGraph->createGraphTool(EventOper::GraphToolType::ToolDirection);
        }

        //清空界面拾取的个数显示，重新初始化为0
        _ui->Pick_num->setText("(0)");

        /*
        根据具体的选项，对创建对象的名称进行修改
        如:选择点拉伸，那么创建对象名称应为Line 此时再去判断是否Line的名称是否重复，由checkName返回一个正确的值
        */
        Acoustics::FITKAcousticsGeometryData* geometryData = FITKAPP->getGlobalData()->getGeometryData<Acoustics::FITKAcousticsGeometryData>();
        if (geometryData == nullptr) return;
        QString name = "";
        QVariant selectType;
        //选择要拾取的类型
        if (type == 0)
        {
            name = geometryData->checkName(tr("Curve-1"));//设置要创建的几何名称
            selectType.setValue(GUI::GUIPickInfo::PickObjType::POBJGeometryVert);//设置该几何由什么创建
        }
        else if (type == 1)
        {
            name = geometryData->checkName(tr("Surface-1"));
            selectType.setValue(GUI::GUIPickInfo::PickObjType::POBJGeometryEdge);
        }
        else if (type == 2)
        {
            name = geometryData->checkName(tr("Solid-1"));
            selectType.setValue(GUI::GUIPickInfo::PickObjType::POBJGeometryFace);
        }
        //设置界面
        _ui->lineEdit_Name->setText(name);
        _ui->stretch_type->setProperty("selectType", selectType);

        /*
        根据选择类型，删除构造函数创建的有限线段对象，创建新的类
        */
        this->typeFromGeometryObj();
    }

    void GUIGeometryStretchDialog::on_pushButton_Pick_clicked()
    {
        /*
        根据选择的模式，设置三维拾取方式
        */
        QVariant var = _ui->stretch_type->property("selectType");
        if (var.canConvert<GUI::GUIPickInfo::PickObjType>())
        {
            GUI::GUIPickInfo::PickObjType typeData = var.value<GUI::GUIPickInfo::PickObjType>();

            switch (typeData)
            {
            case GUI::GUIPickInfo::POBJGeometryVert:
                enablePickSig(GUI::GUIPickInfo::POBJGeometryVert, GUI::GUIPickInfo::PickMethod::PMSingle);
                break;
            case GUI::GUIPickInfo::POBJGeometryEdge:
                enablePickSig(GUI::GUIPickInfo::POBJGeometryEdge, GUI::GUIPickInfo::PickMethod::PMSingle);
                break;
            case GUI::GUIPickInfo::POBJGeometryFace:
                enablePickSig(GUI::GUIPickInfo::POBJGeometryFace, GUI::GUIPickInfo::PickMethod::PMSingle);
                break;
            case GUI::GUIPickInfo::POBJGeometrySolid:
                break;
            default:
                break;
            }

        }
    }

    void GUIGeometryStretchDialog::on_pushButton_OK_clicked()
    {
        QString checkStr = this->checkArgc();//检查参数
        if (checkStr.size() != 0)
        {
            //错误信息汇报
            QMessageBox msgBox;
            msgBox.setIcon(QMessageBox::Warning);  // 设置消息框图标为警告图标
            msgBox.setWindowTitle(tr("warning"));
            msgBox.setText(checkStr);
            msgBox.setStandardButtons(QMessageBox::Ok);  // 设置标准按钮
            msgBox.setDefaultButton(QMessageBox::Ok);  // 设置默认按钮
            int ret = msgBox.exec();//事件循环
            return;
        }

        if (_isCreate)
        {
            if (!this->createObjData())
            {
                return;
            }
        }
        else
        {
            if (!this->editObjData())
                return;
        }
        if (_oper && _obj) {
            _oper->setArgs("objID", _obj->getDataObjectID());
        }
        this->accept();
    }


    void GUIGeometryStretchDialog::on_pushButton_Cancel_clicked()
    {
        _oper->setArgs("objID", -1);
        this->accept();
    }
    void GUIGeometryStretchDialog::on_lineEdit_X_editingFinished()
    {
        this->direction_updata();
    }
    void GUIGeometryStretchDialog::on_lineEdit_Y_editingFinished()
    {
        this->direction_updata();
    }
    void GUIGeometryStretchDialog::on_lineEdit_Z_editingFinished()
    {
        this->direction_updata();
    }
    std::array<double, 3> GUIGeometryStretchDialog::getPointXYZ(int id)
    {
        std::array<double, 3> xyz = { -1,-1,-1 };

        Interface::FITKInterfaceGeometryFactory*factory = Interface::FITKInterfaceGeometryFactory::getInstance();
        if (factory == nullptr)
        {
            return xyz;
        }
        Interface::FITKAbstractGeomToolsCreator*createor = factory->getGeomToolsCreator();
        Interface::FITKAbstractGeomPointTool *pointTool = createor->createPointTool();
        double PointArray[3];
        pointTool->getXYZ(id, PointArray);

        xyz.at(0) = PointArray[0];
        xyz.at(1) = PointArray[1];
        xyz.at(2) = PointArray[2];
        return xyz;
    }
    QString GUIGeometryStretchDialog::checkArgc()
    {

        if (m_pick_num == 0)
        {
            return tr("No pick");
        }

        bool todoubleStatus = false;
        double x = _ui->lineEdit_X->text().toDouble(&todoubleStatus);
        if (todoubleStatus == false)return tr("Illegal value X");
        double y = _ui->lineEdit_Y->text().toDouble(&todoubleStatus);
        if (todoubleStatus == false)return tr("Illegal value Y");
        double z = _ui->lineEdit_Z->text().toDouble(&todoubleStatus);
        if (todoubleStatus == false)return tr("Illegal value Z");

        //全部为0 无方向
        if (x == 0 && y == 0 && z == 0)
        {
            return tr("Need a direction");
        }

        //拉伸长度
        double Value = _ui->lineEdit_Value->text().toDouble(&todoubleStatus);
        if (todoubleStatus == false)
        {
            return tr("Illegal value Value");
        }
        if (Value == 0.0)
        {
            return tr("Value Cannot be 0");
        }
        return "";
    }
    void GUIGeometryStretchDialog::direction_updata()
    {
        //如果方向为0则不更新方向
        double x = _ui->lineEdit_X->text().toDouble();
        double y = _ui->lineEdit_Y->text().toDouble();
        double z = _ui->lineEdit_Z->text().toDouble();
        if (x == 0.0&&y == 0.0&&z == 0.0)
        {
            return;
        }
        EventOper::GraphEventOperator*operGraph = FITKOPERREPO->getOperatorT<EventOper::GraphEventOperator>("OperGraphTool");
        double dir[3] = { 0.0,0.0,0.0 }, pos[3] = { 0.0,0.0,0.0 };
        dir[0] = x;
        dir[1] = y;
        dir[2] = z;

        QVariant var = _ui->stretch_type->property("selectType");
        if (var.canConvert<GUI::GUIPickInfo::PickObjType>())
        {
            GUI::GUIPickInfo::PickObjType typeData = var.value<GUI::GUIPickInfo::PickObjType>();

            switch (typeData)
            {
            case GUI::GUIPickInfo::POBJGeometryVert:
            {
                //由点线
                Interface::FITKAbsGeoModelSegment*lineP = dynamic_cast<Interface::FITKAbsGeoModelSegment*>(_obj);
                if (lineP == nullptr)
                {
                    return;
                }
                std::array<double, 3>Point = lineP->startPoint();
                pos[0] = Point.at(0);
                pos[1] = Point.at(1);
                pos[2] = Point.at(2);

                if (operGraph != nullptr)
                {
                    operGraph->updateDirection(m_direction, dir, pos);
                }
                break;
            }
            case GUI::GUIPickInfo::POBJGeometryEdge:
            {
                //由线创面
                Interface::FITKAbsGeoModelExtrudeSurface*FaceP = dynamic_cast<Interface::FITKAbsGeoModelExtrudeSurface*>(_obj);
                if (FaceP == nullptr)
                {
                    return;
                }
                GraphData::GraphDataCalculate::calculateOCCGeoCenter(FaceP->sourceCurve().VirtualTopoId, pos);
                if (operGraph != nullptr)
                {
                    operGraph->updateDirection(m_direction, dir, pos);
                }
            }
            break;
            case GUI::GUIPickInfo::POBJGeometryFace:
            {
                //由面创体
                Interface::FITKAbsGeoModelExtrudeSolid*SolidP = dynamic_cast<Interface::FITKAbsGeoModelExtrudeSolid*>(_obj);
                if (SolidP == nullptr)
                {
                    return;
                }
                GraphData::GraphDataCalculate::calculateOCCGeoCenter(SolidP->sourceSurface().VirtualTopoId, pos);
                if (operGraph != nullptr)
                {
                    operGraph->updateDirection(m_direction, dir, pos);
                }
            }
            break;
            default:
                break;
            }
        }
    }
    void GUIGeometryStretchDialog::typeFromGeometryObj()
    {
        //首先清理之前创建的几何数据对象
        if (_obj != nullptr)
        {
            delete _obj;
            _obj = nullptr;
        }
        QVariant var = _ui->stretch_type->property("selectType");
        if (var.canConvert<GUI::GUIPickInfo::PickObjType>())
        {
            GUI::GUIPickInfo::PickObjType typeData = var.value<GUI::GUIPickInfo::PickObjType>();

            switch (typeData)
            {
            case GUI::GUIPickInfo::POBJGeometryVert:
                this->createGeometryObj(Interface::FITKGeoEnum::FITKGeometryComType::FGTSegment);//有限线段
                break;
            case GUI::GUIPickInfo::POBJGeometryEdge:
                this->createGeometryObj(Interface::FITKGeoEnum::FITKGeometryComType::FGTExtrudeSurface);// 拉伸面
                break;
            case GUI::GUIPickInfo::POBJGeometryFace:
                this->createGeometryObj(Interface::FITKGeoEnum::FITKGeometryComType::FGTExtrudeSolid);//拉伸体
                break;
            case GUI::GUIPickInfo::POBJGeometrySolid:
                break;
            default:
                break;
            }
        }
    }
}